<!DOCTYPE html>
<html>
<head>
    <title>Michelson Interferometer</title>
    <style>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background-color: #f0f0f0;
        }
        canvas {
            border: 1px solid #ccc;
            background-color: white;
        }
    </style>
</head>
<body>
    <canvas id="canvas" width="800" height="550"></canvas>
    <script>
        const canvas = document.getElementById('canvas');
        const ctx = canvas.getContext('2d');

        // --- Style and Helper Functions ---
        ctx.strokeStyle = 'black';
        ctx.fillStyle = 'black';
        ctx.lineWidth = 2;
        
        function drawArrow(fromX, fromY, toX, toY, headLength = 8) {
            const dx = toX - fromX;
            const dy = toY - fromY;
            const angle = Math.atan2(dy, dx);
            const originalLineWidth = ctx.lineWidth;
            ctx.lineWidth = originalLineWidth; // Use current line width for the line
            ctx.beginPath();
            ctx.moveTo(fromX, fromY);
            ctx.lineTo(toX, toY);
            ctx.stroke();
            
            // Arrowhead
            ctx.beginPath();
            ctx.moveTo(toX, toY);
            ctx.lineTo(toX - headLength * Math.cos(angle - Math.PI / 6), toY - headLength * Math.sin(angle - Math.PI / 6));
            ctx.lineTo(toX - headLength * Math.cos(angle + Math.PI / 6), toY - headLength * Math.sin(angle + Math.PI / 6));
            ctx.closePath();
            ctx.fill();
            ctx.lineWidth = originalLineWidth;
        }

        function drawDoubleArrow(x1, y1, x2, y2, headLength = 8) {
            const dx = x2 - x1;
            const dy = y2 - y1;
            const angle = Math.atan2(dy, dx);
            ctx.beginPath();
            ctx.moveTo(x1, y1);
            ctx.lineTo(x2, y2);
            ctx.stroke();

            // Arrowhead at (x2, y2)
            ctx.beginPath();
            ctx.moveTo(x2, y2);
            ctx.lineTo(x2 - headLength * Math.cos(angle - Math.PI / 6), y2 - headLength * Math.sin(angle - Math.PI / 6));
            ctx.lineTo(x2 - headLength * Math.cos(angle + Math.PI / 6), y2 - headLength * Math.sin(angle + Math.PI / 6));
            ctx.closePath();
            ctx.fill();

            // Arrowhead at (x1, y1)
            const angle2 = Math.atan2(-dy, -dx);
             ctx.beginPath();
            ctx.moveTo(x1, y1);
            ctx.lineTo(x1 - headLength * Math.cos(angle2 - Math.PI / 6), y1 - headLength * Math.sin(angle2 - Math.PI / 6));
            ctx.lineTo(x1 - headLength * Math.cos(angle2 + Math.PI / 6), y1 - headLength * Math.sin(angle2 + Math.PI / 6));
            ctx.closePath();
            ctx.fill();
        }

        // --- Main Drawing ---

        // Part 1: Michelson Interferometer
        const bs_x = 250;
        const bs_y = 250;

        // Source S and incoming beam L0
        const s_x = 80;
        const s_y = 250;
        ctx.beginPath();
        ctx.arc(s_x, s_y, 4, 0, 2 * Math.PI);
        ctx.fill();
        ctx.font = "italic 22px serif";
        ctx.fillText("S", s_x - 20, s_y + 8);

        ctx.lineWidth = 1.5;
        drawArrow(s_x + 5, s_y, bs_x, s_y);
        ctx.font = "italic 22px serif";
        ctx.fillText("L", 150, s_y - 10);
        ctx.font = "16px serif";
        ctx.fillText("0", 162, s_y - 5);

        // Beam Splitter BS
        ctx.lineWidth = 4;
        ctx.beginPath();
        ctx.moveTo(bs_x - 28, bs_y - 28);
        ctx.lineTo(bs_x + 28, bs_y + 28);
        ctx.stroke();
        ctx.font = "20px sans-serif";
        ctx.fillText("BS", bs_x - 60, bs_y + 28);

        ctx.lineWidth = 1.5;

        // Arm 1 (vertical) to Mirror M1
        const m1_y = 100;
        // Rays
        drawArrow(bs_x - 3, bs_y, bs_x - 3, m1_y + 5); // Up
        drawArrow(bs_x + 3, m1_y + 5, bs_x + 3, bs_y); // Down
        // Mirror M1
        ctx.save();
        ctx.fillStyle = '#E0E0E0';
        ctx.fillRect(bs_x - 35, m1_y - 5, 70, 10);
        ctx.lineWidth = 1;
        ctx.strokeRect(bs_x - 35, m1_y - 5, 70, 10);
        ctx.restore();
        // Dotted arc behind M1
        ctx.save();
        ctx.setLineDash([2, 2]);
        ctx.lineWidth = 1;
        ctx.beginPath();
        ctx.arc(bs_x, m1_y + 70, 70, -Math.PI * 0.75, -Math.PI * 0.25);
        ctx.stroke();
        ctx.restore();
        // Labels
        ctx.font = "italic 22px serif";
        ctx.fillText("M", bs_x - 30, m1_y - 15);
        ctx.font = "16px serif";
        ctx.fillText("1", bs_x - 15, m1_y - 10);
        ctx.font = "italic 22px serif";
        ctx.fillText("L", bs_x - 45, bs_y - 70);
        ctx.font = "16px serif";
        ctx.fillText("1", bs_x - 33, bs_y - 65);

        // Arm 2 (horizontal) to Mirror M2
        const m2_x = 430;
        // Rays
        drawArrow(bs_x, bs_y - 3, m2_x - 5, bs_y - 3); // Right
        drawArrow(m2_x - 5, bs_y + 3, bs_x, bs_y + 3); // Left
        // Mirror M2
        ctx.save();
        ctx.fillStyle = '#E0E0E0';
        ctx.fillRect(m2_x - 5, bs_y - 35, 10, 70);
        ctx.lineWidth = 1;
        ctx.strokeRect(m2_x - 5, bs_y - 35, 10, 70);
        ctx.restore();
        // Labels
        ctx.font = "italic 22px serif";
        ctx.fillText("M", m2_x + 10, bs_y - 20);
        ctx.font = "16px serif";
        ctx.fillText("2", m2_x + 25, bs_y - 15);
        ctx.font = "italic 22px serif";
        ctx.fillText("L", bs_x + 80, bs_y - 20);
        ctx.font = "16px serif";
        ctx.fillText("2", bs_x + 92, bs_y - 15);


        // Output beam L and screen axes
        const screen_y = 480;
        ctx.lineWidth = 1.5;
        drawArrow(bs_x, bs_y, bs_x, screen_y);
        ctx.font = "italic 22px serif";
        ctx.fillText("L", bs_x - 25, bs_y + 100);
        // Axes
        ctx.lineWidth = 1;
        drawArrow(bs_x, screen_y, bs_x, screen_y + 60); // z-axis
        drawArrow(bs_x, screen_y, bs_x + 120, screen_y); // x,y-axis
        ctx.font = "italic 20px serif";
        ctx.fillText("z", bs_x - 5, screen_y + 75);
        ctx.fillText("x, y", bs_x + 125, screen_y + 6);

        // Path difference indication (ΔL)
        const arm1_length = bs_y - m1_y; // 150
        const arc_end_x = bs_x + arm1_length; // 250 + 150 = 400
        ctx.save();
        ctx.setLineDash([3, 3]);
        ctx.lineWidth = 1;
        // Arc
        ctx.beginPath();
        ctx.arc(bs_x, bs_y, arm1_length, -Math.PI / 2, 0);
        ctx.stroke();
        // Dashed lines for ΔL
        const dash_y_offset = 30;
        const dash_y_len = 25;
        // Vertical dashed line from arc end
        ctx.beginPath();
        ctx.moveTo(arc_end_x, bs_y + dash_y_offset);
        ctx.lineTo(arc_end_x, bs_y + dash_y_offset + dash_y_len);
        ctx.stroke();
        // Vertical dashed line from M2 pos
        ctx.beginPath();
        ctx.moveTo(m2_x, bs_y + dash_y_offset);
        ctx.lineTo(m2_x, bs_y + dash_y_offset + dash_y_len);
        ctx.stroke();
        ctx.restore();
        // ΔL arrow and label
        ctx.lineWidth = 1.5;
        drawDoubleArrow(arc_end_x, bs_y + dash_y_offset + dash_y_len/2, m2_x, bs_y + dash_y_offset + dash_y_len/2);
        ctx.font = "italic 20px serif";
        ctx.fillText("ΔL", (arc_end_x + m2_x) / 2 - 10, bs_y + dash_y_offset - 2);

        // Part 2: Interference Pattern
        const pat_cx = 620;
        const pat_cy = 280;
        
        // Fringes (painter's algorithm)
        const radii = [110, 105, 96, 88, 80, 71, 62, 52, 40, 25];
        const colors = ['#D3D3D3', 'black'];
        for (let i = 0; i < radii.length; i++) {
            ctx.fillStyle = colors[i % 2];
            ctx.beginPath();
            ctx.arc(pat_cx, pat_cy, radii[i], 0, 2 * Math.PI);
            ctx.fill();
        }

        // Axes on top of pattern
        ctx.strokeStyle = 'black';
        ctx.fillStyle = 'black';
        ctx.lineWidth = 1;
        drawArrow(pat_cx, pat_cy + 130, pat_cx, pat_cy - 130); // y-axis
        drawArrow(pat_cx - 130, pat_cy, pat_cx + 130, pat_cy); // x-axis
        ctx.font = "italic 20px serif";
        ctx.fillText("y", pat_cx - 20, pat_cy - 130);
        ctx.fillText("x", pat_cx + 130, pat_cy + 8);
    </script>
</body>
</html>